package com.yj.ccs.abs.web.asset.service;

import com.yj.ccs.abs.common.enums.*;
import com.yj.ccs.abs.web.asset.dto.*;
import com.yj.ccs.abs.web.asset.entity.*;
import com.yj.ccs.abs.web.asset.mapper.*;
import com.yj.ccs.abs.web.common.mapper.AttachmentMapper;
import com.yj.ccs.abs.web.common.service.CommonService;
import com.yj.ccs.abs.web.management.entity.User;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;

/**
 * Copyright 2018 (C) Yunjian-VC
 * Created on : 2018/3/22
 * Author     : Unbelievable9
 **/
@Service
public class AssetDetailService {

    final private AssetMapper assetMapper;

    final private ContractMapper contractMapper;

    final private PropertyOwnershipMapper propertyOwnershipMapper;

    final private ReceiptMapper receiptMapper;

    final private SettleAccountMapper settleAccountMapper;

    final private FundRestreamMapper fundRestreamMapper;

    final private RemarkMapper remarkMapper;

    final private AttachmentMapper attachmentMapper;

    final private CommonService commonService;

    @Autowired
    public AssetDetailService(AssetMapper assetMapper,
                              ContractMapper contractMapper,
                              PropertyOwnershipMapper propertyOwnershipMapper,
                              ReceiptMapper receiptMapper,
                              SettleAccountMapper settleAccountMapper,
                              FundRestreamMapper fundRestreamMapper,
                              RemarkMapper remarkMapper,
                              AttachmentMapper attachmentMapper,
                              CommonService commonService) {
        this.assetMapper = assetMapper;
        this.contractMapper = contractMapper;
        this.propertyOwnershipMapper = propertyOwnershipMapper;
        this.receiptMapper = receiptMapper;
        this.settleAccountMapper = settleAccountMapper;
        this.fundRestreamMapper = fundRestreamMapper;
        this.remarkMapper = remarkMapper;
        this.attachmentMapper = attachmentMapper;
        this.commonService = commonService;
    }

    public Asset getAssetById(Long id) {
        return assetMapper.getById(id);
    }

    public Contract getContractById(Long id) {
        return contractMapper.getById(id);
    }

    public PropertyOwnership getPropertyOwnershipById(Long id) {
        return propertyOwnershipMapper.getById(id);
    }

    public Receipt getReceiptById(Long id) {
        return receiptMapper.getById(id);
    }

    public SettleAccount getSettleAccountById(Long id) {
        return settleAccountMapper.getById(id);
    }

    public FundRestream getFundRestreamById(Long id) {
        return fundRestreamMapper.getById(id);
    }

    public Remark getRemarkById(Long id) {
        return remarkMapper.getById(id);
    }

    @Transactional
    public void updateBasicInfo(UpdateBasicInfoDto updateBasicInfoDto) {
        Asset asset = new Asset();
        BeanUtils.copyProperties(updateBasicInfoDto, asset);

        assetMapper.update(asset);

        // 保险单
        if (updateBasicInfoDto.getInsured()) {
            attachmentMapper.deleteByIdAndType(asset.getId(), AttachmentType.BASIC_INSURED.getValue());

            if (updateBasicInfoDto.getInsured_files() != null) {
                commonService.setupAttachmentList(updateBasicInfoDto.getInsured_files(), asset.getId(), AttachmentType.BASIC_INSURED);
                attachmentMapper.batchCreate(updateBasicInfoDto.getInsured_files());
            }
        }

        // 担保文件
        if (!updateBasicInfoDto.getGuarantee().equals(AssetGuaranteeType.NONE)) {
            attachmentMapper.deleteByIdAndType(asset.getId(), AttachmentType.BASIC_GUARANTEE.getValue());

            if (updateBasicInfoDto.getGuarantee_files() != null) {
                commonService.setupAttachmentList(updateBasicInfoDto.getGuarantee_files(), asset.getId(), AttachmentType.BASIC_GUARANTEE);
                attachmentMapper.batchCreate(updateBasicInfoDto.getGuarantee_files());
            }
        }

        // 质保文件
        if (updateBasicInfoDto.getDeposited()) {
            attachmentMapper.deleteByIdAndType(asset.getId(), AttachmentType.BASIC_DEPOSITED.getValue());

            if (updateBasicInfoDto.getDeposited_files() != null) {
                commonService.setupAttachmentList(updateBasicInfoDto.getDeposited_files(), asset.getId(), AttachmentType.BASIC_DEPOSITED);
                attachmentMapper.batchCreate(updateBasicInfoDto.getDeposited_files());
            }
        }

        // 展期条款文件
        if (updateBasicInfoDto.getExpanded()) {
            attachmentMapper.deleteByIdAndType(asset.getId(), AttachmentType.BASIC_EXPANDED.getValue());

            if (updateBasicInfoDto.getExpanded_files() != null) {
                commonService.setupAttachmentList(updateBasicInfoDto.getExpanded_files(), asset.getId(), AttachmentType.BASIC_EXPANDED);
                attachmentMapper.batchCreate(updateBasicInfoDto.getExpanded_files());
            }
        }
    }

    @Transactional
    public void updateContract(UpdateContractDto updateContractDto) {
        Contract contract = new Contract();
        BeanUtils.copyProperties(updateContractDto, contract);

        contractMapper.update(contract);

        // 合同影印件
        if (updateContractDto.getFiles() != null) {
            attachmentMapper.deleteByIdAndType(contract.getId(), AttachmentType.CONTRACT_FILE.getValue());

            commonService.setupAttachmentList(updateContractDto.getFiles(), contract.getId(), AttachmentType.CONTRACT_FILE);
            attachmentMapper.batchCreate(updateContractDto.getFiles());
        }

        // 委托运输协议
        if (updateContractDto.getConsigned()) {
            attachmentMapper.deleteByIdAndType(contract.getId(), AttachmentType.CONTRACT_CONSIGNED.getValue());

            if (updateContractDto.getConsigned_files() != null) {
                commonService.setupAttachmentList(updateContractDto.getFiles(), contract.getId(), AttachmentType.CONTRACT_CONSIGNED);
                attachmentMapper.batchCreate(updateContractDto.getFiles());
            }
        }

        // 委托收货协议
        if (updateContractDto.getDelivered()) {
            attachmentMapper.deleteByIdAndType(contract.getId(), AttachmentType.CONTRACT_DELIVERED.getValue());

            if (updateContractDto.getDelivered_files() != null) {
                commonService.setupAttachmentList(updateContractDto.getDelivered_files(), contract.getId(), AttachmentType.CONTRACT_DELIVERED);
                attachmentMapper.batchCreate(updateContractDto.getDelivered_files());
            }
        }

        // 委托结算协议
        if (updateContractDto.getReckoned()) {
            attachmentMapper.deleteByIdAndType(contract.getId(), AttachmentType.CONTRACT_RECKONED.getValue());

            if (updateContractDto.getReckoned_files() != null) {
                commonService.setupAttachmentList(updateContractDto.getReckoned_files(), contract.getId(), AttachmentType.CONTRACT_RECKONED);
                attachmentMapper.batchCreate(updateContractDto.getReckoned_files());
            }
        }
    }

    @Transactional
    public void updatePropertyOwnership(UpdatePropertyOwnershipDto updatePropertyOwnershipDto) {
        PropertyOwnership propertyOwnership = new PropertyOwnership();
        BeanUtils.copyProperties(updatePropertyOwnershipDto, propertyOwnership);

        propertyOwnershipMapper.update(propertyOwnership);

        // 货物照片
        if (updatePropertyOwnershipDto.getProperty_files() != null) {
            attachmentMapper.deleteByIdAndType(propertyOwnership.getId(), AttachmentType.PO_PROPERTY.getValue());

            commonService.setupAttachmentList(updatePropertyOwnershipDto.getProperty_files(), propertyOwnership.getId(), AttachmentType.PO_PROPERTY);
            attachmentMapper.batchCreate(updatePropertyOwnershipDto.getProperty_files());
        }

        // 运输工具照片
        if (updatePropertyOwnershipDto.getTool_files() != null) {
            attachmentMapper.deleteByIdAndType(propertyOwnership.getId(), AttachmentType.PO_TOOL.getValue());

            commonService.setupAttachmentList(updatePropertyOwnershipDto.getTool_files(), propertyOwnership.getId(), AttachmentType.PO_TOOL);
            attachmentMapper.batchCreate(updatePropertyOwnershipDto.getTool_files());
        }

        // 运输照片
        if (updatePropertyOwnershipDto.getTransport_files() != null) {
            attachmentMapper.deleteByIdAndType(propertyOwnership.getId(), AttachmentType.PO_TRANSPORT.getValue());

            commonService.setupAttachmentList(updatePropertyOwnershipDto.getTransport_files(), propertyOwnership.getId(), AttachmentType.PO_TRANSPORT);
            attachmentMapper.batchCreate(updatePropertyOwnershipDto.getTransport_files());
        }

        // 过衡单
        if (updatePropertyOwnershipDto.getSheet_files() != null) {
            attachmentMapper.deleteByIdAndType(propertyOwnership.getId(), AttachmentType.PO_SHEET.getValue());

            commonService.setupAttachmentList(updatePropertyOwnershipDto.getSheet_files(), propertyOwnership.getId(), AttachmentType.PO_SHEET);
            attachmentMapper.batchCreate(updatePropertyOwnershipDto.getSheet_files());
        }

        // 化验单
        if (updatePropertyOwnershipDto.getLaboratory_files() != null) {
            attachmentMapper.deleteByIdAndType(propertyOwnership.getId(), AttachmentType.PO_LABORATORY.getValue());

            commonService.setupAttachmentList(updatePropertyOwnershipDto.getLaboratory_files(), propertyOwnership.getId(), AttachmentType.PO_LABORATORY);
            attachmentMapper.batchCreate(updatePropertyOwnershipDto.getLaboratory_files());
        }

        // 货权转移证明
        if (updatePropertyOwnershipDto.getCert_files() != null) {
            attachmentMapper.deleteByIdAndType(propertyOwnership.getId(), AttachmentType.PO_CERT.getValue());

            commonService.setupAttachmentList(updatePropertyOwnershipDto.getCert_files(), propertyOwnership.getId(), AttachmentType.PO_CERT);
            attachmentMapper.batchCreate(updatePropertyOwnershipDto.getCert_files());
        }
    }

    @Transactional
    public void createReceipt(CreateReceiptDto createReceiptDto) {
        Receipt receipt = new Receipt();
        BeanUtils.copyProperties(createReceiptDto, receipt);

        receiptMapper.create(receipt);

        commonService.setupAttachmentList(createReceiptDto.getFiles(), receipt.getId(), AttachmentType.RECEIPT);

        attachmentMapper.batchCreate(createReceiptDto.getFiles());
    }

    @Transactional
    public void updateReceipt(UpdateReceiptDto updateReceiptDto) {
        Receipt receipt = new Receipt();
        BeanUtils.copyProperties(updateReceiptDto, receipt);

        receiptMapper.update(receipt);

        // 发票文件
        attachmentMapper.deleteByIdAndType(receipt.getId(), AttachmentType.RECEIPT.getValue());

        if (updateReceiptDto.getFiles() != null) {
            commonService.setupAttachmentList(updateReceiptDto.getFiles(), receipt.getId(), AttachmentType.RECEIPT);
            attachmentMapper.batchCreate(updateReceiptDto.getFiles());
        }
    }

    @Transactional
    public void deleteReceipt(Long id) {
        receiptMapper.deleteById(id);

        // 发票文件
        attachmentMapper.deleteByIdAndType(id, AttachmentType.RECEIPT.getValue());
    }

    public ReceiptDetail getReceiptDetail(Receipt receipt) {
        ReceiptDetail receiptDetail = new ReceiptDetail();
        BeanUtils.copyProperties(receipt, receiptDetail);
        receiptDetail.setFiles(attachmentMapper.getByIdAndType(receipt.getId(), AttachmentType.RECEIPT.getValue()));

        return receiptDetail;
    }

    @Transactional
    public void createSettleAccount(CreateSettleAccountDto createSettleAccountDto, Asset asset) {
        SettleAccount settleAccount = new SettleAccount();
        BeanUtils.copyProperties(createSettleAccountDto, settleAccount);

        settleAccountMapper.create(settleAccount);

        commonService.setupAttachmentList(createSettleAccountDto.getFiles(), settleAccount.getId(), AttachmentType.SETTLE_ACCOUNT);

        attachmentMapper.batchCreate(createSettleAccountDto.getFiles());

        assetMapper.updateIsSettledById(true, asset.getId());

        BigDecimal totalPaid = settleAccountMapper.getTotalPriceByAssetId(settleAccount.getAsset_id());

        // 总回款金额 > 应收总金额 资产自动回收
        if (totalPaid.compareTo(asset.getMoney_sum()) > 0) {
        }
    }

    @Transactional
    public void updateSettleAccount(UpdateSettleAccountDto updateSettleAccountDto) {
        SettleAccount settleAccount = new SettleAccount();
        BeanUtils.copyProperties(updateSettleAccountDto, settleAccount);

        settleAccountMapper.update(settleAccount);

        // 结算单据
        attachmentMapper.deleteByIdAndType(settleAccount.getId(), AttachmentType.SETTLE_ACCOUNT.getValue());

        if (updateSettleAccountDto.getFiles() != null) {
            commonService.setupAttachmentList(updateSettleAccountDto.getFiles(), settleAccount.getId(), AttachmentType.SETTLE_ACCOUNT);
            attachmentMapper.batchCreate(updateSettleAccountDto.getFiles());
        }
    }

    @Transactional
    public void deleteSettleAccount(Long id, Long asset_id) {
        settleAccountMapper.deleteById(id);

        // 结算单据
        attachmentMapper.deleteByIdAndType(id, AttachmentType.SETTLE_ACCOUNT.getValue());

        Integer count = settleAccountMapper.getCountByAssetId(asset_id);

        if (count == 0) {
            assetMapper.updateIsSettledById(false, asset_id);
        }
    }

    public SettleAccountDetail getSettleAccountDetail(SettleAccount settleAccount) {
        SettleAccountDetail settleAccountDetail = new SettleAccountDetail();
        BeanUtils.copyProperties(settleAccount, settleAccountDetail);

        settleAccountDetail.setTotal_price(settleAccount.getUnit_price().multiply(settleAccount.getAmount()).setScale(2, RoundingMode.HALF_UP));

        settleAccountDetail.setFiles(attachmentMapper.getByIdAndType(settleAccount.getId(), AttachmentType.SETTLE_ACCOUNT.getValue()));

        return settleAccountDetail;
    }

    @Transactional
    public Boolean createFundRestream(Asset asset, CreateFundRestreamDto createFundRestreamDto, FundRestreamSourceType sourceType) {
        Boolean success = true;

        FundRestream fundRestream = new FundRestream();
        BeanUtils.copyProperties(createFundRestreamDto, fundRestream);
        fundRestream.setSource(sourceType);

        switch (asset.getStatus()) {
            case RECOVERED:
                success = false;
                break;
        }

        if (!success) {
            return false;
        }

        fundRestreamMapper.create(fundRestream);

        // 更新应收应收账款可用余额
        BigDecimal moneyPaid = fundRestreamMapper.countSumMoneyForAssetId(asset.getId());
        BigDecimal moneyAvailable = asset.getMoney_sum().subtract(moneyPaid);

        assetMapper.updateAvailableMoneyById(moneyAvailable, asset.getId());

        if (createFundRestreamDto.getFiles() != null) {
            commonService.setupAttachmentList(createFundRestreamDto.getFiles(), fundRestream.getId(), AttachmentType.FUND_RESTREAM);

            attachmentMapper.batchCreate(createFundRestreamDto.getFiles());
        }

        return true;
    }

    @Transactional
    public void updateFundRestream(UpdateFundRestreamDto updateFundRestreamDto, Asset asset) {
        FundRestream fundRestream = new FundRestream();
        BeanUtils.copyProperties(updateFundRestreamDto, fundRestream);

        fundRestreamMapper.update(fundRestream);

        // 更新应收应收账款可用余额
        BigDecimal moneyPaid = fundRestreamMapper.countSumMoneyForAssetId(asset.getId());
        BigDecimal moneyAvailable = asset.getMoney_sum().subtract(moneyPaid);

        assetMapper.updateAvailableMoneyById(moneyAvailable, asset.getId());

        // 回款单据
        attachmentMapper.deleteByIdAndType(fundRestream.getId(), AttachmentType.FUND_RESTREAM.getValue());

        if (updateFundRestreamDto.getFiles() != null) {
            commonService.setupAttachmentList(updateFundRestreamDto.getFiles(), fundRestream.getId(), AttachmentType.FUND_RESTREAM);
            attachmentMapper.batchCreate(updateFundRestreamDto.getFiles());
        }
    }

    @Transactional
    public void deleteFundRestream(Long id, Asset asset) {
        fundRestreamMapper.deleteById(id);

        // 更新应收应收账款可用余额
        BigDecimal moneyPaid = fundRestreamMapper.countSumMoneyForAssetId(asset.getId());
        BigDecimal moneyAvailable = asset.getMoney_sum().subtract(moneyPaid);

        assetMapper.updateAvailableMoneyById(moneyAvailable, asset.getId());

        // 回款单据
        attachmentMapper.deleteByIdAndType(id, AttachmentType.FUND_RESTREAM.getValue());
    }

    public FundRestreamDetail getFundRestreamDetail(FundRestream fundRestream) {
        FundRestreamDetail fundRestreamDetail = new FundRestreamDetail();
        BeanUtils.copyProperties(fundRestream, fundRestreamDetail);
        fundRestreamDetail.setType(FundRestreamType.fromValue(fundRestream.getType().getValue()));
        fundRestreamDetail.setFiles(attachmentMapper.getByIdAndType(fundRestream.getId(), AttachmentType.FUND_RESTREAM.getValue()));

        return fundRestreamDetail;
    }

    @Transactional
    public void createRemark(CreateRemarkDto createRemarkDto, User user) {
        Remark remark = new Remark();
        BeanUtils.copyProperties(createRemarkDto, remark);
        remark.setDate(LocalDate.now());
        remark.setPerson(user.getUsername());

        if (!remark.getType().equals(RemarkType.EXECUTION)) {
            remark.setFee_date(null);
            remark.setFee_money(BigDecimal.ZERO);
        }

        remarkMapper.create(remark);

        commonService.setupAttachmentList(createRemarkDto.getFiles(), remark.getId(), AttachmentType.REMARK);

        attachmentMapper.batchCreate(createRemarkDto.getFiles());
    }

    @Transactional
    public void updateRemark(UpdateRemarkDto updateRemarkDto, User user) {
        Remark remark = new Remark();
        BeanUtils.copyProperties(updateRemarkDto, remark);

        if (!remark.getType().equals(RemarkType.EXECUTION)) {
            remark.setFee_date(null);
            remark.setFee_money(BigDecimal.ZERO);
        }

        remarkMapper.update(remark);

        // 备注附件
        attachmentMapper.deleteByIdAndType(remark.getId(), AttachmentType.REMARK.getValue());

        if (updateRemarkDto.getFiles() != null) {
            commonService.setupAttachmentList(updateRemarkDto.getFiles(), remark.getId(), AttachmentType.REMARK);
            attachmentMapper.batchCreate(updateRemarkDto.getFiles());
        }
    }

    @Transactional
    public void deleteRemark(Long id) {
        remarkMapper.deleteById(id);

        // 备注附件
        attachmentMapper.deleteByIdAndType(id, AttachmentType.REMARK.getValue());
    }

    public RemarkDetail getRemarkDetail(Remark remark) {
        RemarkDetail remarkDetail = new RemarkDetail();
        BeanUtils.copyProperties(remark, remarkDetail);
        remarkDetail.setType(remark.getType());
        remarkDetail.setFiles(attachmentMapper.getByIdAndType(remark.getId(), AttachmentType.REMARK.getValue()));

        return remarkDetail;
    }
}
